package com.peppa.common.grayconfig;

import com.peppa.common.util.IpUtils;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

import static com.peppa.common.grayconfig.Strategy.Strategy.DELIM_ITEM;
import static com.peppa.common.grayconfig.Strategy.Strategy.DELIM_VALUE;

/**
 * feign转发header中的x-forwarded-for
 * feign转发请求的拦截器
 * @author duge
 */
@Configuration // 注释掉, 不启用该拦截器; 如果启用, 直接打开注释即可
@ConditionalOnProperty(prefix="peppa",name = "gray", havingValue = "true")
public class FeignHeaderRequestInterceptor implements RequestInterceptor {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    public static final String HTTP_X_FORWARDED_FOR = "x-forwarded-for";
    public static final String HUOHUA_PREFIX = "huohua-";
    @Value("${forceHeader:}")
    private String forceHeader;
    private HashMap forceHeaderMap;

    public FeignHeaderRequestInterceptor() {
    }

    @PostConstruct
    private void initForceHeader(){
        if (forceHeader == null || forceHeader.trim().equals("")){
            forceHeaderMap=null;
            return;
        }
        forceHeaderMap = new HashMap();
        try {
            StringTokenizer stringTokenizer = new StringTokenizer(forceHeader,DELIM_ITEM);
            while (stringTokenizer.hasMoreTokens()){
                String str = stringTokenizer.nextToken();
                int ind = str.indexOf(DELIM_VALUE);
                if(ind<=0||str.length()==ind+1)
                    continue;
                String headerkey = str.substring(0,ind).trim();
                String headercont = str.substring(ind+1).trim();
                forceHeaderMap.put(headerkey,headercont);
            }
        }catch (Exception e){
            e.printStackTrace();
            forceHeaderMap = null;
        }
    }

    /**
     * 设置强制在所有的header中添加的元素，这些元素要写在环境变量的forceHeader中
     * @param template
     */
    private void setForceHeader(RequestTemplate template){
        if (forceHeaderMap==null)return;
        try {
            Set<Map.Entry> entries = forceHeaderMap.entrySet();
            for (Map.Entry entry :
                    entries) {
                String key = (String) entry.getKey();
                String Value = (String) entry.getValue();
                template.header(key, Value);
                ThreadAttributes.setThreadAttribute(key,Value);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 往template中传递的是往下游服务传递参数
     * 往attributes中写的是给本地灰度策略用的
     * @param template
     */
    @Override
    public void apply(RequestTemplate template) {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes==null){
                setForceHeader(template);
                logger.warn("attributes==null");
                return;
            }
            HttpServletRequest request = attributes.getRequest();
            Enumeration<String> headerNames = request.getHeaderNames();
            boolean find_xforwardid = false;
            if (headerNames != null) {
                while (headerNames.hasMoreElements()) {
                    String name = headerNames.nextElement();
                    //检查是否有x-forwarded-for属性，如果有直接植入template
                    if (name.equals(HTTP_X_FORWARDED_FOR)) {
                        String values = request.getHeader(name);
                        template.header(name, values);
                        ThreadAttributes.setThreadAttribute(HTTP_X_FORWARDED_FOR,values);
                        find_xforwardid = true;
                    }
                    //所有带huohua-前缀的，都是自定义头，全部继承下去
                    if (name.startsWith(HUOHUA_PREFIX)){
                        String values = request.getHeader(name);
                        template.header(name, values);
                        ThreadAttributes.setThreadAttribute(name,values);
                    }
                }
            }
            //如果没有找到x-forwarded-for属性，则取request的remoteAddr
            //IpUtils.getIpAddr处理了ip的各种情况
            if (!find_xforwardid) {
                String remoteAddr = IpUtils.getIpAddr(request);
                template.header(HTTP_X_FORWARDED_FOR, remoteAddr);
                ThreadAttributes.setThreadAttribute(HTTP_X_FORWARDED_FOR,remoteAddr);
            }
            setForceHeader(template);

            logger.info("feign interceptor header:{}", template);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
